package org.example.demos.pattern.chain_pattern_reference;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.*;

/**
 * 校验控制器
 */
@Slf4j
@Service
public class CheckManager {
 
    @Resource
    private List<IChecker> orderCheckers;
    @Resource
    private List<IChecker> payCheckers;
 
    private static final ThreadPoolExecutor ORDER_POOL = new ThreadPoolExecutor(20, 256,
                    15L, TimeUnit.SECONDS,
                    new LinkedBlockingQueue<>(),
                    (ThreadFactory) Thread::new);
 
    private static final ThreadPoolExecutor PAY_POOL = new ThreadPoolExecutor(20, 128,
                    15L, TimeUnit.SECONDS,
                    new LinkedBlockingQueue<>(),
                    (ThreadFactory) Thread::new);
 
    /**
     * 下单校验
     * @param checkParam
     * @return
     */
    public CheckResult checkOrder(CheckParam checkParam) {
        return checkBase(checkParam, orderCheckers, ORDER_POOL, true);
    }
 
    /**
     * 支付校验
     * @param checkParam
     * @return
     */
    public CheckResult checkPay(CheckParam checkParam) {
        return checkBase(checkParam, payCheckers, PAY_POOL, false);
    }
 
    private CheckResult checkBase(CheckParam checkParam, List<IChecker> checkers, Executor executor, boolean isOrderCheck) {
        // 后续可以根据需要在上下文暂存各校验器公共依赖的基础数据
        CheckContext checkContext = new CheckContext();
        if (!CollectionUtils.isEmpty(checkers)) {
            CompletableFuture[] futures = new CompletableFuture[checkers.size()];
            for (int i = 0; i < checkers.size(); i ++) {
                IChecker checker = checkers.get(i);
                try {
                    futures[i] = CompletableFuture.runAsync(() -> checker.action(checkParam, checkContext), executor);
                } catch (Exception e) {
                    log.error("check_action_error.", e);
                }
            }
            try {
				// 同步获取多个异步结果 超时1500ms
                CompletableFuture.allOf(futures).get(1500, TimeUnit.MILLISECONDS);
            } catch (TimeoutException e) {
                log.error("check_timeout");
            } catch (Exception e) {
                log.error("CheckManager_error", e);
            }
        }
        return getCheckResult(checkContext, isOrderCheck);
    }
 
    private CheckResult getCheckResult(CheckContext checkContext, boolean isOrderCheck) {
        List<String> checkerPipeLine = isOrderCheck ? CheckerConfig.ORDER_CHECKER_PIPELINE : CheckerConfig.PAY_CHECKER_PIPELINE;
        for (String checkerCode : checkerPipeLine) {
            CheckResult checkResult = checkContext.getCheckResultMap().get(checkerCode);
            // 返回第一个被拦截的校验结果
            if (checkResult != null ) {
                return checkResult;
            }
        }
        return new CheckResult();
    }
 
}